#pragma once
#include "dll_export.h"
#include "RemoteEngine.h"

#include <boost/serialization/serialization.hpp>
#include <boost/weak_ptr.hpp>

LUA_DEBUG_BEGIN

/**
* @brief Source title, path, and contents etc.
*/
class _LUAVM_API Source
{
    std::string m_key;
    std::string m_title;
    std::string m_path;
    string_array m_sources;

private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive& ar, const unsigned int) {
        ar & LLDEBUG_MEMBER_NVP(key);
        ar & LLDEBUG_MEMBER_NVP(title);
        ar & LLDEBUG_MEMBER_NVP(path);
        ar & LLDEBUG_MEMBER_NVP(sources);
    }

public:
    explicit Source(const std::string &key,
        const std::string &title,
        const string_array &sources,
        const std::string &path = std::string(""));
    explicit Source();
    ~Source();

    /// Get the source identifier.
    const std::string &GetKey() const {
        return m_key;
    }

    /// Get the source title with utf8.
    const std::string &GetTitle() const {
        return m_title;
    }

    /// Get the path of the source with local encoding, if any.
    const std::string &GetPath() const {
        return m_path;
    }

    /// Get the source contents with utf8.
    const string_array &GetSources() const {
        return m_sources;
    }

    /// Get the line string of the source with utf8.
    string_array::size_type GetLineCount() const {
        return m_sources.size();
    }

    /// Get the number of the source lines.
    const std::string &GetSourceLine(string_array::size_type l) const {
        return m_sources[l];
    }
};

/**
* @brief The manager of the source files displayed when debugging.
*/
class _LUAVM_API SourceManager
{
    boost::weak_ptr<RemoteEngine> m_engine;

    typedef std::map<std::string, Source> ImplMap;
    ImplMap m_sourceMap;
    int m_textCounter;

public:
    explicit SourceManager(RemoteEngine_ptr engine);
    ~SourceManager();

    /// Get the source infomation from key.
    const Source *Get(const std::string &key);

    /// Get the string source by the first part of the key.
    const Source *GetString(const std::string &key);

    /// Get the string source
    std::list<Source> GetList();

    /// Add a source.
    int AddSource(const Source &source, bool sendRemote);

    /// Add a source.
    int Add(const std::string &key, const std::string &src);

    /// Save a source.
    int Save(const std::string &key, const string_array &source);
};

LUA_DEBUG_END
